/*
 * JSF Toolkit Component Framework
 * Copyright (C) 2007 Noah Sloan <iamnoah A-T gmail D0T com>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 */
package com.jsftoolkit.gen.info;

import com.jsftoolkit.utils.Utils;

/**
 * Metadata describing the configuration files to update for a component.
 * 
 * @author noah
 * 
 */
public class ConfigInfo {

	public static final String DEFAULT_CONFIG_DIR = "src/main/resources/META-INF/";

	private ComponentInfo component;

	private String facesConfig;

	private String taglibXml;

	private String tldFile;

	private String tagName;

	private String namespace;

	private String libraryShortName;

	private String registerClass;

	private String registerRenderer;

	/**
	 * Default constructor.
	 */
	public ConfigInfo() {
		super();
		initDefaults();
	}

	/**
	 * 
	 * @param component
	 *            the parent component
	 */
	public ConfigInfo(ComponentInfo component) {
		this();
		this.component = component;
	}

	public static ConfigInfo newWithDefaults(ComponentInfo component) {
		ConfigInfo info = new ConfigInfo(component);
		info.initDefaults();
		return info;
	}

	private void initDefaults() {
		facesConfig = DEFAULT_CONFIG_DIR + "faces-config.xml";
		taglibXml = DEFAULT_CONFIG_DIR + "components.taglib.xml";
		tldFile = DEFAULT_CONFIG_DIR + "components.tld";
	}

	/**
	 * 
	 * @param facesConfig
	 * @param taglibXml
	 * @param tldFile
	 */
	public ConfigInfo(String facesConfig, String taglibXml, String tldFile) {
		this(facesConfig, taglibXml, tldFile, null, null, null);
	}

	/**
	 * Convenience constructor.
	 * 
	 * @param facesConfig
	 * @param taglibXml
	 * @param tldFile
	 * @param tagName
	 * @param namespace
	 * @param libraryShortName
	 */
	public ConfigInfo(String facesConfig, String taglibXml, String tldFile,
			String tagName, String namespace, String libraryShortName) {
		this();
		this.facesConfig = facesConfig;
		this.taglibXml = taglibXml;
		this.tldFile = tldFile;
		setTagName(tagName);
		setNamespace(namespace);
		setLibraryShortName(libraryShortName);
	}

	/**
	 * 
	 * @return the path to faces-config.xml (or some other faces config file) to
	 *         update to include this component.
	 */
	public String getFacesConfig() {
		return facesConfig;
	}

	public void setFacesConfig(String facesConfig) {
		this.facesConfig = facesConfig;
	}

	/**
	 * 
	 * @return the value that should be given to the short-name element for any
	 *         TLD file generated for this component.
	 */
	public String getLibraryShortName() {
		return libraryShortName == null ? getDefaultShortname()
				: libraryShortName;
	}

	/**
	 * 
	 * @return a guess at the short name, by taking the second part of the
	 *         component's package name
	 */
	protected String getDefaultShortname() {
		if (component == null) {
			return null;
		}
		String _package = component.getPackage();
		String[] split = Utils.split(_package, "\\.");

		// skip the .com,.net,.edu, whatever
		return Utils.get(split, 1, _package);
	}

	public void setLibraryShortName(String libraryShortName) {
		if (libraryShortName != null) {
			this.libraryShortName = libraryShortName;
		}
	}

	/**
	 * 
	 * @return the namespace to be used for taglib.xml and TLD files.
	 */
	public String getNamespace() {
		return namespace == null ? getDefaultNamespace() : namespace;
	}

	/**
	 * 
	 * @return tries to guess the namespace from the component package name
	 */
	protected String getDefaultNamespace() {
		String[] split = Utils.split(component.getPackage(), "\\.");

		// take a guess that the first 3 parts of the package name are the
		// domain name
		int len = Math.min(3, split.length);
		return "http://" + Utils.join(split, ".", len - 1, -len)
				+ "/components";

	}

	public void setNamespace(String namespace) {
		if (namespace != null) {
			this.namespace = namespace;
		}
	}

	/**
	 * 
	 * @return the .tablib.xml file to update for this component.
	 */
	public String getTaglibXml() {
		return taglibXml;
	}

	public void setTaglibXml(String taglibXml) {
		this.taglibXml = taglibXml;
	}

	/**
	 * 
	 * @return the name of the tag for this component
	 */
	public String getTagName() {
		return Utils.getValue(tagName, component == null ? null : Utils
				.uncapitalize(component.getActualClassName()));
	}

	public void setTagName(String tagName) {
		if (tagName != null) {
			this.tagName = tagName;
		}
	}

	/**
	 * 
	 * @return the path to the TLD file to update for this component.
	 */
	public String getTldFile() {
		return tldFile;
	}

	public void setTldFile(String tldFile) {
		this.tldFile = tldFile;
	}

	/**
	 * 
	 * @return the ComponentInfo for the component
	 */
	public ComponentInfo getComponent() {
		return component;
	}

	public void setComponent(ComponentInfo component) {
		this.component = component;
	}

	/**
	 * 
	 * @return the name of the class to register in config files
	 */
	public String getRegisterClass() {
		return registerClass == null && component != null ? component
				.getActualCannonicalName() : registerClass;
	}

	public void setRegisterClass(String register) {
		this.registerClass = register;
	}

	/**
	 * If registerRenderer was set, returns that value. Otherwise returns the
	 * canonical class name from the RenderInfo returned by
	 * component.getRenderer(), or null if there isn't one.
	 * 
	 * @return the class of the renderer to register
	 */
	public String getRegisterRenderer() {
		RendererInfo renderer = component == null ? null : component
				.getRenderer();
		return registerRenderer == null && renderer != null ? renderer
				.getActualCannonicalName() : registerRenderer;
	}

	public void setRegisterRenderer(String registerRenderer) {
		this.registerRenderer = registerRenderer;
	}

}
